# GNAFU - "Ground, Navy and Air Fuck-Up" real-time strategy game
# Copyright (C) 2008-2009 k0wax <k0waxk0wax@gmail.com>
#
# This file is part of GNAFU.
#
# GNAFU is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GNAFU is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNAFU.  If not, see <http://www.gnu.org/licenses/>.

from __future__ import division, absolute_import
import weakref
from src import vars

class EntityController(object):
    max_enity_id = 0
    entities = weakref.WeakValueDictionary()
    @classmethod
    def set_next_entity_id(self):
        self.max_enity_id += 1
        return self.max_enity_id
     
class BaseEntity(object):
    """Any world's object"""
    _ctl = EntityController # FIXME
    def __init__(self, x=0, y=0, parent=None): 
        self._x = x
        self._y = y
        self.visible = True
        self.selectable = True
        self.parent = None
        self.entity_id = BaseEntity._ctl.set_next_entity_id()
        BaseEntity._ctl.entities[self.entity_id] = self
    @property
    def position(self):
        return (self.x, self.y)
    # fixme
    @property
    def x(self): return self._x if not self.parent else self.parent.x + self._x
    @property
    def y(self): return self._y if not self.parent else self.parent.y + self._y
    @x.setter
    def x(self, val): self._x = val
    @y.setter
    def y(self, val): self._y = val
    def set_parent(self, parent):
        self.parent = parent
    def set_child(self, child):
        raise NotImplementedError
        
class StaticFieldEntity(BaseEntity):
    def __init__(self, cx=0, cy=0):
        self.cx, self.cy = cx, cy
        x = self.cx * vars.tile_size
        y = self.cy * vars.tile_size
        super(StaticFieldEntity, self).__init__(x, y)
        
class StaticEntity(BaseEntity):
    def __init__(self, x=0, y=0):
        super(StaticEntity, self).__init__(x, y)
        
class Entity(BaseEntity):
    """Dynamic, movable, rotatable entity"""
    def __init__(self, x=0, y=0, dir=0):
        super(Entity, self).__init__(x, y)
        self.dx, self.dy = 0, 0
        self.dst_x, self.dst_y = None, None
        self._dir = dir # degrees
        self._dst_dir = None
        self.dir_lock = False
        self.locked = False
        self.moving_lock = False
        self.rot_lock = False
    def _set_dir(self, val):
        self._dir = val % 360
    dir = property(lambda self: self._dir, _set_dir)
    def _set_dst_dir(self, val):
        if val == None:
            self.dir_lock = False
        elif val != self.dir:
            self.dir_lock = True
            val %= 360
        self._dst_dir = val
    dst_dir = property(lambda self: self._dst_dir, _set_dst_dir)
    def handle_dir(self, dt):
        inc = self.dir_speed
        if self.dir - self.dst_dir > self.dst_dir - self.dir:
            inc = -inc
        self.dir += inc * dt
        if self.dst_dir // self.dir_step == self.dir // self.dir_step: # unset dst_dir, fixme
            self.dir = self.dst_dir
            self.dst_dir = None
    def update(self, dt):
        if self.dir_lock == True:
            self.handle_dir(dt)

class EntityGroup(BaseEntity):
    """Not implemented"""
    def __init__(self):
        self.components = []
    def add_to_group(self, en):
        self.components.append(en)
